import Decimal from 'decimal.js'

/**
 * @description add  加
 * @description sub  减
 * @description mul  乘
 * @description div  除
 */
export const Decimals = {
	add: (a: any, b: any) => Number(new Decimal(Number(a)).add(new Decimal(Number(b)))),
	sub: (a: any, b: any) => Number(new Decimal(Number(a)).sub(new Decimal(Number(b)))),
	mul: (a: any, b: any) => Number(new Decimal(Number(a)).mul(new Decimal(Number(b)))),
	div: (a: any, b: any) => Number(new Decimal(Number(a)).div(new Decimal(Number(b))))
}

/**
 * 将数字或数字字符串转换为带千分位的字符串
 * @param value - 数字或数字字符串
 * @param decimals - 保留的小数位数，默认为不保留小数
 * @returns 带千分位格式化的字符串
 */
export function formatToThousands(value: number | string, decimals: number = 0): string {
	// 确保输入是有效的数字
	const number = typeof value === 'string' ? parseFloat(value) : value

	if (isNaN(number)) {
		throw new Error('Invalid input: Please provide a valid number or numeric string')
	}

	// 将数字转换为带指定小数位的字符串
	const formattedNumber = number.toFixed(decimals)

	// 使用正则表达式为整数部分添加千分位
	const [integerPart, decimalPart] = formattedNumber.split('.')
	const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',')

	return decimalPart ? `${formattedInteger}.${decimalPart}` : formattedInteger
}

/**
 * 将数字或数字字符串转换为带千分位的字符串
 * @param value - 数字或数字字符串
 * @param decimals - 保留的小数位数，默认为不保留小数
 * @returns 带千分位格式化的字符串
 */
export function formatToThousandsWithDecimal(value: number | string, decimals: number = 0): string {
	// 创建 Decimal 实例
	let decimalValue: Decimal
	try {
		decimalValue = new Decimal(value)
	} catch (error) {
		throw new Error('Invalid input: Please provide a valid number or numeric string')
	}

	// 保留指定小数位数
	const formattedNumber = decimalValue.toFixed(decimals)

	// 将结果拆分为整数部分和小数部分
	const [integerPart, decimalPart] = formattedNumber.split('.')

	// 使用正则表达式格式化整数部分
	const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',')

	return decimalPart ? `${formattedInteger}.${decimalPart}` : formattedInteger
}

/**
 * type 区分法币和加密货币：

    fiat：处理法币，支持 PC 和 H5 不同展示规则。
    crypto：加密货币固定显示 8 位小数。
    platform 区分平台：
    pc：法币完整显示，不使用 KMB 格式。
    h5：法币使用 KMB 格式（千、百万等），最多显示两位小数。
    KMB 格式实现：通过循环将数字除以 1000，找到对应的缩写单位（K、M、B）。
    最终组合缩写单位和格式化后的数值。
    错误处理：如果输入不是数字（或不能被转换为有效数字），抛出错误，避免程序运行时异常。
 * @param value 
 * @param options 
 * @returns 
 */
export function formatNumber(
	value: number | string,
	options: {
		type: 'fiat' | 'crypto' // 法币 or 加密货币
		platform: 'pc' | 'h5' // 平台
	}
): string {
	const num = typeof value === 'string' ? parseFloat(value) : value

	// 检查是否为有效数字
	if (isNaN(num)) {
		throw new Error('Invalid number input')
	}

	// 小数显示规则
	const fiatDecimals = options.platform === 'pc' ? 0 : 2
	const cryptoDecimals = 8

	// KMB 格式规则
	const abbreviations = ['', 'K', 'M', 'B']
	const getAbbreviation = (value: number): { value: number; unit: string } => {
		let unitIndex = 0
		let newValue = value
		while (newValue >= 1000 && unitIndex < abbreviations.length - 1) {
			newValue /= 1000
			unitIndex++
		}
		return { value: newValue, unit: abbreviations[unitIndex] }
	}

	if (options.type === 'fiat') {
		if (options.platform === 'pc') {
			// PC 平台：不进位，完整显示
			return num.toLocaleString(undefined, {
				minimumFractionDigits: fiatDecimals,
				maximumFractionDigits: fiatDecimals
			})
		} else {
			// H5 平台：使用 KMB 格式，显示两位小数
			const { value, unit } = getAbbreviation(num)
			return `${value.toFixed(2)}${unit}`
		}
	} else if (options.type === 'crypto') {
		// 加密货币：显示8位小数
		return num.toFixed(cryptoDecimals)
	}

	return num.toString()
}
